﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Globalization;
using Microsoft.SharePoint;

namespace E4D.Solutions.SPRNuGet.EventReceivers.Helpers
{
    /// <summary>
    /// This class is based on a class from NuGet sourcecode on CodePlex: http://nuget.codeplex.com
    /// </summary>
    internal static class ManifestSchemaUtility
    {
        private const string SchemaNamespaceToken = "!!Schema version!!";
        /// <summary>
        /// Baseline schema 
        /// </summary>
        internal const string SchemaVersionV1 = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd";

        /// <summary>
        /// Added copyrights, references and release notes
        /// </summary>
        internal const string SchemaVersionV2 = "http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd";

        /// <summary>
        /// Used if the version is a semantic version.
        /// </summary>
        internal const string SchemaVersionV3 = "http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd";

        private static readonly string[] VersionToSchemaMappings = new[] {
            SchemaVersionV1,
            SchemaVersionV2,
            SchemaVersionV3,
        };

        private static Dictionary<string, string> _schemaCache = new Dictionary<string, string>();

        // Mapping from schema to resource name
        private static readonly Dictionary<string, string> SchemaToResourceMappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
            { SchemaVersionV1, "NuGet.Authoring.nuspec.xsd" },
            { SchemaVersionV2, "NuGet.Authoring.nuspec.xsd" },
            { SchemaVersionV3, "NuGet.Authoring.nuspec.xsd" },
        };

        public static bool IsKnownSchema(string schemaNamespace)
        {
            return SchemaToResourceMappings.ContainsKey(schemaNamespace);
        }
        
        public static TextReader GetSchemaReader(string schemaNamespace, string siteUrl)
        {
            string schemaResourceName;
            if (!SchemaToResourceMappings.TryGetValue(schemaNamespace, out schemaResourceName))
            {
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Invalid schema namespace '{0}'.",
                    schemaNamespace));
            }


            if (_schemaCache.ContainsKey(schemaNamespace))
            {
                return new StringReader(_schemaCache[schemaNamespace]);
            }
            else
            {
                using (SPSite site = new SPSite(siteUrl))
                {
                    using (SPWeb web = site.RootWeb)
                    {
                        SPFolder folder = web.Folders[siteUrl + "/SPRNugetSupportFiles/"];
                        SPFile file = folder.Files["nuspec.xsd"];
                        using (var reader = new StreamReader(file.OpenBinaryStream()))
                        {
                            string content = reader.ReadToEnd();
                            content = String.Format(CultureInfo.InvariantCulture, content, schemaNamespace);
                            _schemaCache.Add(schemaNamespace, content);
                        }
                    }
                }
            }
            return new StringReader(_schemaCache[schemaNamespace]);
        }
    }
}
